* use implict conversions for lat,lon degs<->rads.
* use Position* return values.
* convert grtcirc i/f to PositionDeg, PositionRad.
* fix mac compile, denote converting ctor.
* inline PositionDeg/Rad converting ctors.
* respect PosotionX encapsulation.
* differentiate member names for PositionDeg, PositiionRad. This can catch unintended usages where the type is not what was expected.
* clean up unneccesary usage of Waypoint::position.
* delete obsolete declaration.
* spell
* update garmin include
* consistenly unpack Positions to consts in grtcirc.
* provide default initializers for PositionX.
void ArcDistanceFilter::arcdist_arc_disp_wpt_cb(const Waypoint* arcpt2)
{
static const Waypoint* arcpt1 = nullptr;
- double prjlat;
- double prjlon;
+ PositionDeg prjpos;
double frac;
if (arcpt2 && arcpt2->latitude != BADVAL && arcpt2->longitude != BADVAL &&
if (ed->distance == BADVAL || projectopt || ed->distance >= pos_dist) {
double dist;
if (ptsopt) {
- dist = gcdist(RAD(arcpt2->latitude),
- RAD(arcpt2->longitude),
- RAD(waypointp->latitude),
- RAD(waypointp->longitude));
- prjlat = arcpt2->latitude;
- prjlon = arcpt2->longitude;
+ dist = gcdist(arcpt2->position(), waypointp->position());
+ prjpos = arcpt2->position();
frac = 1.0;
} else {
if (waypointp == nullptr) {
fatal(FatalMsg() << "Internal error: Attempt to project waypoint without predecessor");
}
- dist = linedistprj(arcpt1->latitude,
- arcpt1->longitude,
- arcpt2->latitude,
- arcpt2->longitude,
- waypointp->latitude,
- waypointp->longitude,
- &prjlat, &prjlon, &frac);
+ std::tie(dist, prjpos, frac) = linedistprj(arcpt1->position(),
+ arcpt2->position(),
+ waypointp->position());
}
/* convert radians to float point statute miles */
if (ed->distance > dist) {
ed->distance = dist;
if (projectopt) {
- ed->prjlatitude = prjlat;
- ed->prjlongitude = prjlon;
+ ed->prjpos = prjpos;
ed->frac = frac;
ed->arcpt1 = arcpt1;
ed->arcpt2 = arcpt2;
wp->wpt_flags.marked_for_deletion = 1;
removed++;
} else if (projectopt) {
- wp->longitude = ed->prjlongitude;
- wp->latitude = ed->prjlatitude;
+ wp->SetPosition(ed->prjpos);
if (!arcfileopt &&
(ed->arcpt2->altitude != unknown_alt) &&
(ptsopt || (ed->arcpt1->altitude != unknown_alt))) {
struct extra_data {
double distance;
- double prjlatitude;
- double prjlongitude;
+ PositionDeg prjpos;
double frac;
const Waypoint* arcpt1;
const Waypoint* arcpt2;
Waypoint* BendFilter::create_wpt_dest(const Waypoint* wpt_orig, const Waypoint* wpt_orig_adj) const
{
- double distance = radtometers(gcdist(RAD(wpt_orig->latitude), RAD(wpt_orig->longitude),
- RAD(wpt_orig_adj->latitude), RAD(wpt_orig_adj->longitude)));
+ double distance = radtometers(gcdist(wpt_orig->position(),
+ wpt_orig_adj->position()));
if (distance <= maxDist) {
return nullptr;
}
double frac = maxDist / distance;
auto* wpt_dest = new Waypoint(*wpt_orig);
- linepart(wpt_orig->latitude, wpt_orig->longitude,
- wpt_orig_adj->latitude, wpt_orig_adj->longitude,
- frac,
- &wpt_dest->latitude, &wpt_dest->longitude);
+ wpt_dest->SetPosition(linepart(wpt_orig->position(), wpt_orig_adj->position(), frac));
return wpt_dest;
}
const Waypoint* wpt_orig_prev,
const Waypoint* wpt_orig_next) const
{
- double lat_orig = RAD(wpt_orig->latitude);
- double long_orig = RAD(wpt_orig->longitude);
-
- double lat_orig_prev = RAD(wpt_orig_prev->latitude);
- double long_orig_prev = RAD(wpt_orig_prev->longitude);
-
- double lat_orig_next = RAD(wpt_orig_next->latitude);
- double long_orig_next = RAD(wpt_orig_next->longitude);
-
- double heading_prev = heading_true_degrees(lat_orig, long_orig,
- lat_orig_prev, long_orig_prev);
- double heading_next = heading_true_degrees(lat_orig, long_orig,
- lat_orig_next, long_orig_next);
+ double heading_prev = heading_true_degrees(wpt_orig->position(),
+ wpt_orig_prev->position());
+ double heading_next = heading_true_degrees(wpt_orig->position(),
+ wpt_orig_next->position());
double heading_diff = heading_next - heading_prev;
#ifndef DEFS_H_INCLUDED_
#define DEFS_H_INCLUDED_
+#include <cmath> // for nan
#include <cstddef> // for NULL, nullptr_t, size_t
#include <cstdint> // for int32_t, uint32_t
#include <cstdio> // for NULL, fprintf, FILE, stdout
#include <ctime> // for time_t
+#include <numbers> // for inv_pi, pi
#include <optional> // for optional
#include <utility> // for move
/* knots(nautical miles/hour) to meters/second */
constexpr double KNOTS_TO_MPS(double a) {return a * kMPSPerKnot;}
+/* Degrees to radians */
+constexpr double kDegreesPerRadian = 180.0 * std::numbers::inv_pi;
+constexpr double DEG(double x) { return x * kDegreesPerRadian; }
+
+/* Radians to degrees */
+constexpr double kRadiansPerDegree = 1.0 / kDegreesPerRadian;
+constexpr double RAD(double x) { return x * kRadiansPerDegree; }
+
constexpr int kDatumOSGB36 = 86; // GPS_Lookup_Datum_Index("OSGB36")
constexpr int kDatumWGS84 = 118; // GPS_Lookup_Datum_Index("WGS 84")
double min_alt; /* -unknown_alt => invalid */
};
+struct PositionRad; // forward declare
+struct PositionDeg
+{
+ PositionDeg() = default;
+ explicit(false) inline PositionDeg(const PositionRad& posr); /* converting ctor */
+ PositionDeg(double latd, double lond) : latD(latd), lonD(lond) {}
+
+ double latD{std::nan("")};
+ double lonD{std::nan("")};
+};
+
+struct PositionRad
+{
+ PositionRad() = default;
+ explicit(false) inline PositionRad(const PositionDeg& posd); /* converting ctor */
+ PositionRad(double latr, double lonr) : latR(latr), lonR(lonr) {}
+
+ double latR{std::nan("")};
+ double lonR{std::nan("")};
+};
+
+inline PositionDeg::PositionDeg(const PositionRad& posr) :
+ latD(posr.latR * kDegreesPerRadian),
+ lonD(posr.lonR * kDegreesPerRadian) {}
+
+inline PositionRad::PositionRad(const PositionDeg& posd) :
+ latR(posd.latD * kRadiansPerDegree),
+ lonR(posd.lonD * kRadiansPerDegree) {}
+
/*
* This is a waypoint, as stored in the GPSR. It tries to not
* cater to any specific model or protocol. Anything that needs to
void SetCreationTime(qint64 t, qint64 ms = 0);
Geocache* AllocGCData();
int EmptyGCData() const;
+ PositionDeg position() const {return PositionDeg(latitude, longitude);}
+ void SetPosition(const PositionDeg& pos)
+ {
+ latitude = pos.latD;
+ longitude = pos.lonD;
+ }
// mimic std::optional interface, but use our more space
// efficient wp_flags.
#include "garmin_fs.h" // for garmin_fs_garmin_after_read, garmin_fs_garmin_before_write
#include "garmin_tables.h" // for gt_find_icon_number_from_desc, PCX, gt_find_desc_from_icon_number
#include "geocache.h" // for Geocache, Geocache::type_t, Geocache...
-#include "grtcirc.h" // for DEG
#include "jeeps/gpsapp.h" // for GPS_Set_Baud_Rate, GPS_Init, GPS_Pre...
#include "jeeps/gpscom.h" // for GPS_Command_Get_Lap, GPS_Command_Get...
#include "jeeps/gpsmem.h" // for GPS_Track_Del, GPS_Way_Del, GPS_Pvt_Del
/* At this point we have found a waypoint with same name,
but probably from another data stream. Check coordinates!
*/
- double dist = radtometers(gcdist(
- RAD(ref->latitude), RAD(ref->longitude),
- RAD(tmp->latitude), RAD(tmp->longitude)));
+ double dist = radtometers(gcdist(ref->position(), tmp->position()));
if (fabs(dist) > 100) {
fatal(MYNAME ": Route point mismatch!\n" \
#include <cerrno> // for errno, EDOM
#include <cmath> // for cos, sin, fabs, atan2, sqrt, asin, atan, isnan
#include <numbers> // for pi
-#include <tuple> // for make_tuple, tuple
+#include <tuple> // for tie, tuple, make_tuple, ignore
-#include "defs.h" // for METERS_TO_MILES
+#include "defs.h" // for PositionRad, DEG, METERS_TO_MILES, PositionDeg
+#include "grtcirc.h"
static constexpr double EARTH_RAD = 6378137.0;
return (x1 * x2 + y1 * y2 + z1 * z2);
}
-/*
- * Note: this conversion to miles uses the WGS84 value for the radius of
- * the earth at the equator.
- * (radius in meters)*(100cm/m) -> (radius in cm)
- * (radius in cm) / (2.54 cm/in) -> (radius in in)
- * (radius in in) / (12 in/ft) -> (radius in ft)
- * (radius in ft) / (5280 ft/mi) -> (radius in mi)
- * If the compiler is half-decent, it'll do all the math for us at compile
- * time, so why not leave the expression human-readable?
- */
-
double radtomiles(double rads)
{
constexpr double radmiles = METERS_TO_MILES(EARTH_RAD);
return (rads * EARTH_RAD);
}
-double gcdist(double lat1, double lon1, double lat2, double lon2)
+double gcdist(PositionRad pos1, PositionRad pos2)
{
errno = 0;
+ const double lat1 = pos1.latR;
+ const double lon1 = pos1.lonR;
+ const double lat2 = pos2.latR;
+ const double lon2 = pos2.lonR;
+
double sdlat = sin((lat1 - lat2) / 2.0);
double sdlon = sin((lon1 - lon2) / 2.0);
/* This value is the heading you'd leave point 1 at to arrive at point 2.
* Inputs and outputs are in radians.
*/
-static double heading(double lat1, double lon1, double lat2, double lon2)
+static double heading(PositionRad pos1, PositionRad pos2)
{
+ const double lat1 = pos1.latR;
+ const double lon1 = pos1.lonR;
+ const double lat2 = pos2.latR;
+ const double lon2 = pos2.lonR;
+
double v1 = sin(lon2 - lon1) * cos(lat2);
double v2 = cos(lat1) * sin(lat2) - sin(lat1) * cos(lat2) * cos(lon2 - lon1);
/* rounding error protection */
return atan2(v1, v2);
}
-/* As above, but outputs is in degrees from 0 - 359. Inputs are still radians. */
-double heading_true_degrees(double lat1, double lon1, double lat2, double lon2)
+double heading_true_degrees(PositionRad pos1, PositionRad pos2)
{
- double h = 360.0 + DEG(heading(lat1, lon1, lat2, lon2));
+ double h = 360.0 + DEG(heading(pos1, pos2));
if (h >= 360.0) {
h -= 360.0;
}
// Note: This is probably not going to vectorize as it uses statics internally,
// so it's hard for the optimizer to prove it's a pure function with no side
// effects, right?
-double linedistprj(double lat1, double lon1,
- double lat2, double lon2,
- double lat3, double lon3,
- double* prjlat, double* prjlon,
- double* frac)
+std::tuple<double, PositionDeg, double> linedistprj(PositionRad pos1,
+ PositionRad pos2,
+ PositionRad pos3)
{
static double _lat1 = -9999;
static double _lat2 = -9999;
double dot;
- *prjlat = lat1;
- *prjlon = lon1;
- *frac = 0;
+ /* prjpos must be of type PositionRad as we assign
+ * prjpos.lat, prjpos.lon below in radians.
+ */
+ PositionRad prjpos = pos1;
- /* degrees to radians */
- lat1 = RAD(lat1);
- lon1 = RAD(lon1);
- lat2 = RAD(lat2);
- lon2 = RAD(lon2);
- lat3 = RAD(lat3);
- lon3 = RAD(lon3);
+ double frac = 0;
+
+ /* we use these values below assuming they are in radians,
+ * => posn must be of type PositionRad.
+ */
+ const double lat1 = pos1.latR;
+ const double lon1 = pos1.lonR;
+ const double lat2 = pos2.latR;
+ const double lon2 = pos2.lonR;
+ const double lat3 = pos3.latR;
+ const double lon3 = pos3.lonR;
bool newpoints = true;
if (lat1 == _lat1 && lat2 == _lat2 && lon1 == _lon1 && lon2 == _lon2) {
/* 'a' is the axis; the line that passes through the center of the earth
* and is perpendicular to the great circle through point 1 and point 2
* It is computed by taking the cross product of the '1' and '2' vectors.*/
- auto [xt, yt, zt] = crossproduct(x1, y1, z1, x2, y2, z2);
- xa = xt;
- ya = yt;
- za = zt;
+ std::tie(xa, ya, za) = crossproduct(x1, y1, z1, x2, y2, z2);
la = sqrt(xa * xa + ya * ya + za * za);
if (la) {
* atan2 would be overkill because lp and fabs(dot) are both
* known to be positive. */
- *prjlat = DEG(asin(yp));
+ prjpos.latR = asin(yp);
if (xp == 0 && zp == 0) {
- *prjlon = 0;
+ prjpos.lonR = 0;
} else {
- *prjlon = DEG(atan2(zp, xp));
+ prjpos.lonR = atan2(zp, xp);
}
- *frac = d1 / (d1 + d2);
+ frac = d1 / (d1 + d2);
- return atan(fabs(dot) / lp);
+ return {atan(fabs(dot) / lp), prjpos , frac};
}
/* otherwise, get the distance from the closest endpoint */
}
if (fabs(d1) < fabs(d2)) {
- return gcdist(lat1, lon1, lat3, lon3);
+ return {gcdist(pos1, pos3), prjpos, frac};
} else {
- *prjlat = DEG(lat2);
- *prjlon = DEG(lon2);
- *frac = 1.0;
- return gcdist(lat2, lon2, lat3, lon3);
+ prjpos = pos2;
+ frac = 1.0;
+ return {gcdist(pos2, pos3), prjpos, frac};
}
} else {
/* lp is 0 when 3 is 90 degrees from the great circle */
- return std::numbers::pi / 2;
+ return {std::numbers::pi / 2, prjpos, frac};
}
} else {
/* la is 0 when 1 and 2 are either the same point or 180 degrees apart */
dot = dotproduct(x1, y1, z1, x2, y2, z2);
if (dot >= 0) {
- return gcdist(lat1, lon1, lat3, lon3);
+ return {gcdist(pos1, pos3), prjpos, frac};
} else {
- return 0;
+ return {0, prjpos, frac};
}
}
}
-double linedist(double lat1, double lon1,
- double lat2, double lon2,
- double lat3, double lon3)
+double linedist(PositionRad pos1, PositionRad pos2, PositionRad pos3)
{
- double dummy;
- return linedistprj(lat1, lon1, lat2, lon2, lat3, lon3, &dummy, &dummy, &dummy);
+ double dist;
+ std::tie(dist, std::ignore, std::ignore) = linedistprj(pos1, pos2, pos3);
+ return dist;
}
/*
* Ref: http://mathworld.wolfram.com/RotationFormula.html
*/
-void linepart(double lat1, double lon1,
- double lat2, double lon2,
- double frac,
- double* reslat, double* reslon)
+PositionDeg linepart(PositionRad pos1, PositionRad pos2, double frac)
{
- /* result must be in degrees */
- *reslat = lat1;
- *reslon = lon1;
-
- /* degrees to radians */
- lat1 = RAD(lat1);
- lon1 = RAD(lon1);
- lat2 = RAD(lat2);
- lon2 = RAD(lon2);
+ /* respos must be of type PositionRad as we assign
+ * respos.lat, respos.lon below in radians.
+ */
+ PositionRad respos = pos1;
+
+ /* we use these values below assuming they are in radians,
+ * => posn must be of type PositionRad.
+ */
+ const double lat1 = pos1.latR;
+ const double lon1 = pos1.lonR;
+ const double lat2 = pos2.latR;
+ const double lon2 = pos2.lonR;
/* polar to ECEF rectangular */
double x1 = cos(lon1) * cos(lat1);
yr = std::clamp(yr, -1.0, 1.0);
zr = std::clamp(zr, -1.0, 1.0);
- *reslat = DEG(asin(yr));
+ respos.latR = asin(yr);
if (xr == 0 && zr == 0) {
- *reslon = 0;
+ respos.lonR = 0;
} else {
- *reslon = DEG(atan2(zr, xr));
+ respos.lonR = atan2(zr, xr);
}
}
+ return respos;
}
#ifndef GRTCIRC_H
#define GRTCIRC_H
-#include <numbers> // for inv_pi
+#include <tuple> // for tuple
+#include "defs.h" // for PositionRad, PositionDeg
-double gcdist(double lat1, double lon1, double lat2, double lon2);
-double heading_true_degrees(double lat1, double lon1, double lat2, double lon2);
+/* Note PositionDeg and PositionRad can be implicity converted to
+ * each other, so you may use either to interface to these functions.
+ */
+
+double gcdist(PositionRad pos1, PositionRad pos2);
+double heading_true_degrees(PositionRad pos1, PositionRad pos2);
-double linedistprj(double lat1, double lon1,
- double lat2, double lon2,
- double lat3, double lon3,
- double* prjlat, double* prjlon,
- double* frac);
+std::tuple<double, PositionDeg, double> linedistprj(PositionRad pos1,
+ PositionRad pos2,
+ PositionRad pos3);
-double linedist(double lat1, double lon1,
- double lat2, double lon2,
- double lat3, double lon3);
+double linedist(PositionRad pos1, PositionRad pos2, PositionRad pos3);
double radtometers(double rads);
double radtomiles(double rads);
-void linepart(double lat1, double lon1,
- double lat2, double lon2,
- double frac,
- double* reslat, double* reslon);
-
-/* Degrees to radians */
-constexpr double kDegreesPerRadian = 180.0 * std::numbers::inv_pi;
-constexpr double DEG(double x) { return x * kDegreesPerRadian; }
-
-/* Radians to degrees */
-constexpr double kRadiansPerDegree = 1.0 / kDegreesPerRadian;
-constexpr double RAD(double x) { return x * kRadiansPerDegree; }
-
+PositionDeg linepart(PositionRad pos1, PositionRad pos2, double frac);
#endif
// Get a crude indication of groundspeed from the change in lat/lon
int deltat_msec = (*wpt_rit)->GetCreationTime().msecsTo(wpt->GetCreationTime());
speed = (deltat_msec == 0) ? 0:
- radtometers(gcdist(RAD(wpt->latitude), RAD(wpt->longitude),
- RAD((*wpt_rit)->latitude), RAD((*wpt_rit)->longitude))) /
+ radtometers(gcdist(wpt->position(), (*wpt_rit)->position())) /
(0.001 * deltat_msec);
if (global_opts.debug_level >= 2) {
printf(MYNAME ": speed=%.2fm/s\n", speed);
}
// And add them back, with interpolated points interspersed.
- double lat1 = 0;
- double lon1 = 0;
+ PositionDeg pos1;
double altitude1 = unknown_alt;
gpsbabel::DateTime time1;
bool first = true;
// interpolate even if time is running backwards.
npts = std::abs(*timespan) / max_time_step;
} else if (opt_dist != nullptr) {
- double distspan = radtomiles(gcdist(RAD(lat1),
- RAD(lon1),
- RAD(wpt->latitude),
- RAD(wpt->longitude)));
+ double distspan = radtomiles(gcdist(pos1, wpt->position()));
npts = distspan / max_dist_step;
}
if (!std::isfinite(npts) || (npts >= INT_MAX)) {
} else {
wpt_new->creation_time = gpsbabel::DateTime();
}
- linepart(lat1, lon1,
- wpt->latitude, wpt->longitude,
- frac,
- &wpt_new->latitude,
- &wpt_new->longitude);
+ wpt_new->SetPosition(linepart(pos1, wpt->position(), frac));
if (altspan.has_value()) {
wpt_new->altitude = altitude1 + (frac * *altspan);
} else {
track_add_wpt(rte, wpt);
}
- lat1 = wpt->latitude;
- lon1 = wpt->longitude;
+ pos1 = wpt->position();
altitude1 = wpt->altitude;
time1 = wpt->creation_time.toUTC(); // use utc to avoid tz conversions.
}
} else {
Waypoint* newest_posn= posn_trk_head->waypoint_list.back();
- if (radtometers(gcdist(RAD(wpt->latitude), RAD(wpt->longitude),
- RAD(newest_posn->latitude), RAD(newest_posn->longitude))) > 50) {
+ if (radtometers(gcdist(wpt->position(), newest_posn->position())) > 50) {
track_add_wpt(posn_trk_head, new Waypoint(*wpt));
} else {
/* If we haven't move more than our threshold, pretend
for (int j = i + 1 ; j < nelems ; ++j) {
if (!qlist.at(j).deleted) {
- double dist = gc_distance(qlist.at(j).wpt->latitude,
- qlist.at(j).wpt->longitude,
- qlist.at(i).wpt->latitude,
- qlist.at(i).wpt->longitude);
+ double dist = radtometers(gcdist(qlist.at(j).wpt->position(),
+ qlist.at(i).wpt->position()));
if (dist <= pos_dist) {
if (check_time) {
/* Member Functions */
- static double gc_distance(double lat1, double lon1, double lat2, double lon2)
- {
- return radtometers(gcdist(RAD(lat1), RAD(lon1), RAD(lat2), RAD(lon2)));
- }
void position_runqueue(const WaypointList& waypt_list, int qtype);
/* Data Members */
void RadiusFilter::process()
{
foreach (Waypoint* waypointp, *global_waypoint_list) {
- double dist = gc_distance(waypointp->latitude, waypointp->longitude,
- home_pos->latitude, home_pos->longitude);
+ double dist = radtomiles(gcdist(waypointp->position(),
+ home_pos->position()));
if ((dist >= pos_dist) == (exclopt == nullptr)) {
waypointp->wpt_flags.marked_for_deletion = 1;
/* Member Functions */
- static double gc_distance(double lat1, double lon1, double lat2, double lon2)
- {
- return radtomiles(gcdist(RAD(lat1), RAD(lon1), RAD(lat2), RAD(lon2)));
- }
-
/* Data Members */
double pos_dist{};
/*
* gcdist and heading want radians, not degrees.
*/
- double tlat = RAD(thisw->latitude);
- double tlon = RAD(thisw->longitude);
- double plat = RAD(prev->latitude);
- double plon = RAD(prev->longitude);
if (!thisw->course_has_value()) {
// Only recompute course if the waypoint
// didn't already have a course.
- thisw->set_course(heading_true_degrees(plat, plon, tlat, tlon));
+ thisw->set_course(heading_true_degrees(prev->position(), thisw->position()));
}
- double dist = radtometers(gcdist(plat, plon, tlat, tlon));
+ double dist = radtometers(gcdist(prev->position(), thisw->position()));
tdata.distance_meters += dist;
/*
switch (metric) {
case metric_t::crosstrack:
track_error = radtomiles(linedist(
- wpt1->latitude, wpt1->longitude,
- wpt2->latitude, wpt2->longitude,
- wpt3->latitude, wpt3->longitude));
+ wpt1->position(),
+ wpt2->position(),
+ wpt3->position()));
break;
case metric_t::length:
track_error = radtomiles(
- gcdist(RAD(wpt1->latitude), RAD(wpt1->longitude),
- RAD(wpt3->latitude), RAD(wpt3->longitude)) +
- gcdist(RAD(wpt3->latitude), RAD(wpt3->longitude),
- RAD(wpt2->latitude), RAD(wpt2->longitude)) -
- gcdist(RAD(wpt1->latitude), RAD(wpt1->longitude),
- RAD(wpt2->latitude), RAD(wpt2->longitude)));
+ gcdist(wpt1->position(), wpt3->position()) +
+ gcdist(wpt3->position(), wpt2->position()) -
+ gcdist(wpt1->position(), wpt2->position()));
break;
case metric_t::relative:
default: // eliminate false positive warning with g++ 11.3.0: ‘error’ may be used uninitialized in this function [-Wmaybe-uninitialized]
(wpt1->GetCreationTime() != wpt2->GetCreationTime())) {
double frac = static_cast<double>(wpt1->GetCreationTime().msecsTo(wpt3->GetCreationTime())) /
static_cast<double>(wpt1->GetCreationTime().msecsTo(wpt2->GetCreationTime()));
- double reslat;
- double reslon;
- linepart(wpt1->latitude, wpt1->longitude,
- wpt2->latitude, wpt2->longitude,
- frac, &reslat, &reslon);
- track_error = radtometers(gcdist(
- RAD(wpt3->latitude), RAD(wpt3->longitude),
- RAD(reslat), RAD(reslon)));
+ auto respos = linepart(wpt1->position(),
+ wpt2->position(),
+ frac);
+ track_error = radtometers(gcdist(wpt3->position(), respos));
} else { // else distance to connecting line
track_error = radtometers(linedist(
- wpt1->latitude, wpt1->longitude,
- wpt2->latitude, wpt2->longitude,
- wpt3->latitude, wpt3->longitude));
+ wpt1->position(),
+ wpt2->position(),
+ wpt3->position()));
}
// error relative to horizontal precision
track_error /= (6 * wpt3->hdop);
if (distance > 0) {
double curdist = radtometers(
- gcdist(RAD(prev_wpt->latitude), RAD(prev_wpt->longitude),
- RAD(wpt->latitude), RAD(wpt->longitude)));
+ gcdist(prev_wpt->position(), wpt->position()));
if (curdist <= distance) {
new_track_flag = false;
} else if constexpr(TRACKF_DBG) {
void TrackFilter::trackfilter_synth()
{
- double last_course_lat;
- double last_course_lon;
- double last_speed_lat = std::nan(""); /* Quiet gcc 7.3.0 -Wmaybe-uninitialized */
- double last_speed_lon = std::nan(""); /* Quiet gcc 7.3.0 -Wmaybe-uninitialized */
+ PositionDeg last_course_pos;
+ PositionDeg last_speed_pos;
gpsbabel::DateTime last_speed_time;
int nsats = 0;
wpt->reset_speed();
}
first = false;
- last_course_lat = wpt->latitude;
- last_course_lon = wpt->longitude;
- last_speed_lat = wpt->latitude;
- last_speed_lon = wpt->longitude;
+ last_course_pos = wpt->position();
+ last_speed_pos = wpt->position();
last_speed_time = wpt->GetCreationTime();
} else {
if (opt_course) {
- wpt->set_course(heading_true_degrees(RAD(last_course_lat),
- RAD(last_course_lon),RAD(wpt->latitude),
- RAD(wpt->longitude)));
- last_course_lat = wpt->latitude;
- last_course_lon = wpt->longitude;
+ wpt->set_course(heading_true_degrees(last_course_pos,
+ wpt->position()));
+ last_course_pos = wpt->position();
}
if (opt_speed) {
if (last_speed_time.msecsTo(wpt->GetCreationTime()) != 0) {
// Note that points with the same time can occur because the input
// has truncated times, or because we are truncating times with
// toTime_t().
- wpt->set_speed(radtometers(gcdist(
- RAD(last_speed_lat), RAD(last_speed_lon),
- RAD(wpt->latitude),
- RAD(wpt->longitude))) /
+ wpt->set_speed(radtometers(gcdist(last_speed_pos, wpt->position()))
+ /
(0.001 * std::abs(last_speed_time.msecsTo(wpt->GetCreationTime())))
);
- last_speed_lat = wpt->latitude;
- last_speed_lon = wpt->longitude;
+ last_speed_pos = wpt->position();
last_speed_time = wpt->GetCreationTime();
} else {
wpt->reset_speed();
bool TrackFilter::trackfilter_points_are_same(const Waypoint* wpta, const Waypoint* wptb)
{
return
- radtometers(gcdist(RAD(wpta->latitude),
- RAD(wpta->longitude),
- RAD(wptb->latitude),
- RAD(wptb->longitude))) < kDistanceLimit &&
+ radtometers(gcdist(wpta->position(), wptb->position())) < kDistanceLimit &&
std::abs(wpta->altitude - wptb->altitude) < 20 &&
wpta->courses_equal(*wptb) &&
wpta->speeds_equal(*wptb) &&
for (auto it = wptlist.cbegin(); it != wptlist.cend(); ++it) {
auto* wpt = *it;
if (it != wptlist.cbegin()) {
- double cur_dist = radtometers(gcdist(RAD(prev_wpt->latitude),
- RAD(prev_wpt->longitude),
- RAD(wpt->latitude),
- RAD(wpt->longitude)));
+ double cur_dist = radtometers(gcdist(prev_wpt->position(),
+ wpt->position()));
// Denoise points that are on top of each other,
// keeping the first and last of the group.
wpt->AddUrlLink(UrlLink(link, url_link_text, url_link_type));
}
+// TODO: change inputs to PositionDeg?
double
gcgeodist(const double lat1, const double lon1,
const double lat2, const double lon2)
{
- return radtometers(gcdist(RAD(lat1), RAD(lon1), RAD(lat2), RAD(lon2)));
+ return radtometers(gcdist(PositionDeg(lat1, lon1), PositionDeg(lat2, lon2)));
}
/*
waypt_course(const Waypoint* A, const Waypoint* B)
{
if (A && B) {
- return heading_true_degrees(RAD(A->latitude), RAD(A->longitude), RAD(B->latitude), RAD(B->longitude));
+ return heading_true_degrees(A->position(), B->position());
} else {
return 0;
}
XcsvFormat::xcsv_resetpathlen(const route_head* head)
{
pathdist = 0;
- oldlat = 999;
- oldlon = 999;
+ old_position.reset();
csv_route = csv_track = nullptr;
switch (xcsv_style->datatype) {
case trkdata:
double utmn;
char utmzc;
- if (oldlon < 900) {
- pathdist += radtometers(gcdist(RAD(oldlat),RAD(oldlon),
- RAD(wpt->latitude),RAD(wpt->longitude)));
+ if (old_position) {
+ pathdist += radtometers(gcdist(old_position.value(),
+ wpt->position()));
}
- longitude = oldlon = wpt->longitude;
- latitude = oldlat = wpt->latitude;
+ old_position = wpt->position();
+ latitude = wpt->latitude;
+ longitude = wpt->longitude;
QString write_delimiter;
if (xcsv_style->field_delimiter == u"\\w") {
XcsvFile* xcsv_file{nullptr};
const XcsvStyle* xcsv_style{nullptr};
double pathdist = 0;
- double oldlon = 999;
- double oldlat = 999;
+ std::optional<PositionDeg> old_position;
int waypt_out_count = 0;
const route_head* csv_track = nullptr;